import hashlib

from django.db import models

from sysreptor.pentests import querysets, storages
from sysreptor.users.models import PentestUser
from sysreptor.utils.crypto.fields import EncryptedField
from sysreptor.utils.history import HistoricalRecords
from sysreptor.utils.models import BaseModel


class UploadedFileBase(BaseModel):
    file = models.FileField()
    name = EncryptedField(base_field=models.CharField(max_length=255))
    name_hash = models.BinaryField(max_length=32, db_index=True)

    class Meta(BaseModel.Meta):
        abstract = True
        unique_together = [['linked_object', 'name_hash']]

    @classmethod
    def hash_name(cls, name) -> bytes:
        return hashlib.sha3_256(name.encode()).digest()

    def save(self, *args, **kwargs):
        self.name_hash = self.hash_name(self.name)
        return super().save(*args, **kwargs)


class UploadedImage(UploadedFileBase):
    file = models.ImageField(storage=storages.get_uploaded_image_storage)
    linked_object = models.ForeignKey(to='PentestProject', on_delete=models.CASCADE, related_name='images')

    history = HistoricalRecords()
    objects = querysets.UploadedImageManager()


class UploadedAsset(UploadedFileBase):
    file = models.FileField(storage=storages.get_uploaded_asset_storage)
    linked_object = models.ForeignKey(to='ProjectType', on_delete=models.CASCADE, related_name='assets')

    history = HistoricalRecords()
    objects = querysets.UploadedAssetManager()


class UploadedTemplateImage(UploadedFileBase):
    file = models.ImageField(storage=storages.get_uploaded_image_storage)
    linked_object = models.ForeignKey(to='FindingTemplate', on_delete=models.CASCADE, related_name='images')

    history = HistoricalRecords()
    objects = querysets.UploadedTemplateImageManager()


class UploadedProjectFile(UploadedFileBase):
    file = models.FileField(storage=storages.get_uploaded_file_storage)
    linked_object = models.ForeignKey(to='PentestProject', on_delete=models.CASCADE, related_name='files')

    history = HistoricalRecords()
    objects = querysets.UploadedProjectFileManager()


class UploadedUserNotebookImage(UploadedFileBase):
    file = models.ImageField(storage=storages.get_uploaded_image_storage)
    linked_object = models.ForeignKey(to=PentestUser, on_delete=models.CASCADE, related_name='images')

    objects = querysets.UploadedUserNotebookImageManager()


class UploadedUserNotebookFile(UploadedFileBase):
    file = models.FileField(storage=storages.get_uploaded_file_storage)
    linked_object = models.ForeignKey(to=PentestUser, on_delete=models.CASCADE, related_name='files')

    objects = querysets.UploadedUserNotebookFileManager()


class ProjectNotebookExcalidrawFile(BaseModel):
    file = models.FileField(storage=storages.get_uploaded_file_storage)
    linked_object = models.OneToOneField(to='ProjectNotebookPage', on_delete=models.CASCADE, unique=True, related_name='excalidraw_file')

    history = HistoricalRecords()


class UserNotebookExcalidrawFile(BaseModel):
    file = models.FileField(storage=storages.get_uploaded_file_storage)
    linked_object = models.OneToOneField(to='UserNotebookPage', on_delete=models.CASCADE, unique=True, related_name='excalidraw_file')

